package com.nrg.richie.client;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.Style.SelectionMode;
import com.extjs.gxt.ui.client.core.XTemplate;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.Store;
import com.extjs.gxt.ui.client.store.StoreSorter;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.TabItem;
import com.extjs.gxt.ui.client.widget.TabPanel;
import com.extjs.gxt.ui.client.widget.VerticalPanel;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.FileUploadField;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.form.FormPanel.Encoding;
import com.extjs.gxt.ui.client.widget.form.FormPanel.Method;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.grid.CheckBoxSelectionModel;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.RowExpander;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.nrg.richie.shared.AdFilterConstants;
import com.nrg.richie.shared.NodeData;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class AdFilter implements EntryPoint {

	/**
	 * Create a remote service proxy to talk to the server-side XML data controller service.
	 */
	private final XmlDataControllerServiceAsync xmlDataControllerService = GWT.create(XmlDataControllerService.class);

	private AdFilterConstants constants = GWT.create(AdFilterConstants.class);
	
	private final VerticalPanel mainPanel = new VerticalPanel();
	private MessageBox wait;
    private final ContentPanel cp = new ContentPanel();  

	private final TabPanel tabPanel = new TabPanel();

	private final FormPanel uploadPanel = new FormPanel();  
	private final FormPanel readPanel = new FormPanel(); 
		/**
		 * This is the entry point method.
		 */
	public void onModuleLoad() {

		
		Document.get().setTitle(constants.pageHeaderText());
		RootPanel.get("header").add(new HTML(constants.pageHeaderText()));

		tabPanel.setSize(350, 200);
		TabItem uploadTabItem = new TabItem(constants.uploadTabItem());
		TabItem readTabItem = new TabItem(constants.readTabItem());
		
		tabPanel.add(readTabItem);
		tabPanel.add(uploadTabItem);

	    readTabItem.add(readPanel);
		uploadTabItem.add(uploadPanel);

	    readPanel.setHeading(constants.readPanelHeader());  
	    readPanel.setFrame(true);  
	    readPanel.setMethod(Method.POST);  
	    readPanel.setAction("/readServlet"); 
	    readPanel.setButtonAlign(HorizontalAlignment.CENTER);  
	    readPanel.setSize(350, 175); 
		
		
	    final TextField<String> url = new TextField<String>();
	    url.setAllowBlank(false);  
	    url.setName("url");  
	    url.setFieldLabel(constants.readURL());  
	    url.setValue(constants.defaultUrl());
	    readPanel.add(url);  

	    final TextField<String> userName = new TextField<String>();
	    userName.setAllowBlank(false);  
	    userName.setName("userName");  
	    userName.setFieldLabel(constants.userName());  
	    userName.setValue(constants.defaultUser());
	    readPanel.add(userName); 	    
	    
	    final TextField<String> password = new TextField<String>();
	    password.setAllowBlank(false);  
	    password.setName("password");  
	    password.setFieldLabel(constants.password());
	    password.setPassword(true);
	    readPanel.add(password); 	    

	    final Button resetReadPanelButton = new Button(constants.resetButton());  
	    resetReadPanelButton.addSelectionListener(new SelectionListener<ButtonEvent>() {  
			@Override  
			public void componentSelected(ButtonEvent ce) {  
				readPanel.reset();  
			}  
	    });  
	    readPanel.addButton(resetReadPanelButton);  
	    
	    
	    final Button readButton = new Button(constants.readButton());  
	    readButton.addSelectionListener(new SelectionListener<ButtonEvent>() {  
			@Override  
			public void componentSelected(ButtonEvent ce) {  
				if (!readPanel.isValid()) {  
					return;  
				}  
				readPanel.submit();  
			}  	      
	    });  
	    
	    readPanel.addButton(readButton);  
	  
	    readPanel.addListener(Events.BeforeSubmit, new Listener<BaseEvent>() {
	    	
	    	public void handleEvent(BaseEvent event) {

				readButton.disable();
				wait = MessageBox.wait(constants.readText(), constants.readInProgress(), constants.readText());		    		  

	    	};
	    	
		});
	    
	    
	    readPanel.addListener(Events.Submit, new Listener<BaseEvent>() {
	    	
	    	public void handleEvent(BaseEvent event) {
	    		

				xmlDataControllerService.getNodeDataList(new AsyncCallback<List<NodeData>>() {
					
					@Override
					public void onSuccess(List<NodeData> result) {
						
						displayTable(result);
						
					}
					
					@Override
					public void onFailure(Throwable caught) {
			    		wait.close();
			    		readButton.enable();
			    		MessageBox.alert(constants.error(), constants.readError(), null);
			    		
			    	}
				});					

	    	};
	    	
		});	    

		
	    uploadPanel.setHeading(constants.uploadPanelHeader());  
	    uploadPanel.setFrame(true);  
	    uploadPanel.setAction("/uploadServlet");  
	    uploadPanel.setEncoding(Encoding.MULTIPART);  
	    uploadPanel.setMethod(Method.POST);  
	    uploadPanel.setButtonAlign(HorizontalAlignment.CENTER);  
	    uploadPanel.setSize(350, 175);  
	  
	    final FileUploadField file = new FileUploadField();  
	    file.setAllowBlank(false);  
	    file.setName("file");  
	    file.setFieldLabel(constants.uploadFileName());  
	    uploadPanel.add(file);  
	  
	    final Button resetUploadPanelButton = new Button(constants.resetButton());  
	    resetUploadPanelButton.addSelectionListener(new SelectionListener<ButtonEvent>() {  
			@Override  
			public void componentSelected(ButtonEvent ce) {  
				uploadPanel.reset();  
			}  
	    });  
	    uploadPanel.addButton(resetUploadPanelButton);  
	    
	    
	    final Button uploadButton = new Button(constants.uploadButton());  
	    uploadButton.addSelectionListener(new SelectionListener<ButtonEvent>() {  
			@Override  
			public void componentSelected(ButtonEvent ce) {  
				if (!uploadPanel.isValid()) {  
					return;  
				}  
				uploadPanel.submit();  
			}  	      
	    });  
	    
	    uploadPanel.addButton(uploadButton);  
	  
	    uploadPanel.addListener(Events.BeforeSubmit, new Listener<BaseEvent>() {
	    	
	    	public void handleEvent(BaseEvent event) {

				if (file.getValue() == null || file.getValue().trim().length() == 0) {
					MessageBox.alert(constants.error(), constants.uploadFileNameIsRequired(), null);
					event.setCancelled(true);
				} else {
					uploadButton.disable();
					wait = MessageBox.wait(constants.uploadText(), constants.uploadInProgress(), constants.uploadText());		    		  
				}		    		
	    	};
	    	
		});
	    
	    uploadPanel.addListener(Events.Submit, new Listener<BaseEvent>() {
	    	
	    	public void handleEvent(BaseEvent event) {
	    		

				xmlDataControllerService.getNodeDataList(new AsyncCallback<List<NodeData>>() {
					
					@Override
					public void onSuccess(List<NodeData> result) {
						
						displayTable(result);
						
					}
					
					@Override
					public void onFailure(Throwable caught) {
			    		wait.close();
			    		uploadButton.enable();
			    		MessageBox.alert(constants.error(), constants.uploadError(), null);					}
				});					

	    	};
	    	
		});

	    mainPanel.add(tabPanel);

		RootPanel.get("root").add(mainPanel);

	}
	
	private void displayTable(List<NodeData> result) {

		tabPanel.setVisible(false);
		
		NumberFormat currency = NumberFormat.getCurrencyFormat();
		
		List<NodeData> preSelectionList = new ArrayList<NodeData>();
		
		for (NodeData nodeData : result) {
			try {
				double price = Double.parseDouble(nodeData.getPrice());								
				nodeData.setDisplayPrice(currency.format(price));
			} catch (Exception e) { }
			
			if (nodeData.getPreSelected().equalsIgnoreCase(Boolean.TRUE.toString())) {
				preSelectionList.add(nodeData);								
			}

		}

		wait.close();
		
		List<ColumnConfig> configs = new ArrayList<ColumnConfig>();  

	    XTemplate tpl = XTemplate.create(constants.summaryTemplate());  
		  
	    RowExpander expander = new RowExpander();  
	    expander.setTemplate(tpl);  
	  
	    configs.add(expander);  
	    
	    final CheckBoxSelectionModel<NodeData> sm = new CheckBoxSelectionModel<NodeData>() {
	    	
	    	@Override

	    	protected void handleMouseDown(GridEvent<NodeData> e) {

	        	if (e.getColIndex() == 1 && e.getEvent().getButton() == NativeEvent.BUTTON_LEFT) { 
	        		NodeData m = listStore.getAt(e.getRowIndex());
    				if (m != null) {
    			        if (isSelected(m)) {
    						doDeselect(Arrays.asList(m), false);
    					} else {
    						doSelect(Arrays.asList(m), true, false);
    					}
    				}
    			}
	    	}
	    	
	    	@Override
	    	protected void onSelectChange(NodeData model, boolean select) {

	    		super.onSelectChange(model, select);
	    		
	    		cp.setHeading(constants.tableHeader() + " (" + this.getSelectedItems().size() + " " + constants.tableHeaderSelected() + ")"); 
	    		
	    	}
	    	
	    };  
	    sm.setSelectionMode(SelectionMode.SIMPLE);
	    
	    configs.add(sm.getColumn());  
	  
	    ColumnConfig column = new ColumnConfig();  
	    column.setId("referenceNumber");  
	    column.setHeader(constants.tableHeaderReferenceNumber());  
	    column.setWidth(100);  
	    configs.add(column);  

	    column = new ColumnConfig();  
	    column.setId("type");  
	    column.setHeader(constants.tableHeaderType());  
	    column.setWidth(125); 
	    configs.add(column);  

	    column = new ColumnConfig();  
	    column.setId("city");  
	    column.setHeader(constants.tableHeaderCity());  
	    column.setWidth(125);  
	    configs.add(column);  

	    column = new ColumnConfig();  
	    column.setId("description");  
	    column.setHeader(constants.tableHeaderDescription());  
	    column.setWidth(100);  
	    configs.add(column);  

	    column = new ColumnConfig();  
	    column.setId("phoneNumber");  
	    column.setHeader(constants.tableHeaderPhoneNumber());  
	    column.setWidth(100);  
	    configs.add(column);  	    	    
	    
	    column = new ColumnConfig();  
	    column.setId("displayPrice");  
	    column.setHeader(constants.tableHeaderPrice());  
	    column.setAlignment(HorizontalAlignment.RIGHT);  
	    column.setWidth(100); 
	    configs.add(column);  

	    ListStore<NodeData> store = new ListStore<NodeData>();  
	    store.add(result);  

	    store.setStoreSorter(new StoreSorter<NodeData>() {
	    	@Override
	    	public int compare(Store<NodeData> store, NodeData m1, NodeData m2, String property) {
	    		
	    		try {
		    		if (property.equals("displayPrice")) {
		    			Double price1 = Double.parseDouble(m1.getPrice());
		    			Double price2 = Double.parseDouble(m2.getPrice());
		    			
		    			return price1.compareTo(price2);
		    		}
	    		} catch (Exception e) {}
	    		
	    		return super.compare(store, m1, m2, property);
	    	}
	    });							    
	    
	    ColumnModel cm = new ColumnModel(configs);  
	  
	    cp.setHeading(constants.tableHeader());  
	    cp.setFrame(true);  
	    
	    Button export = new Button(constants.exportButton());
	    
	    export.addSelectionListener(new SelectionListener<ButtonEvent>() {  
			@Override  
			public void componentSelected(ButtonEvent ce) {
				
				if (sm.getSelectedItems().size() > 0) {
					xmlDataControllerService.setExportNodeDataList(sm.getSelectedItems(), new AsyncCallback<Void>() {
						
						@Override
						public void onSuccess(Void result) {										
							String copyURL = GWT.getModuleBaseURL() + "downloadServlet";

							new DownloadIFrame(copyURL);
						}
						
						@Override
						public void onFailure(Throwable caught) {
							MessageBox.alert(constants.error(), constants.exportError(), null);
							
						}
					});
				} else {
					MessageBox.info(constants.systemMessage(), constants.noRowsSelected(), null);
				}
				
			}  	      
	    });
	    
	    cp.addButton(export);  
	    
	    Button startOver = new Button(constants.startOverButton());
	    
	    startOver.addSelectionListener(new SelectionListener<ButtonEvent>() {  
			@Override  
			public void componentSelected(ButtonEvent ce) {  

				xmlDataControllerService.resetSession(new AsyncCallback<Void>() {
					
					@Override
					public void onSuccess(Void result) {
						Window.Location.reload();
					}
					
					@Override
					public void onFailure(Throwable caught) {
						Window.Location.reload();
					}
				});
				
			}  	      
	    });
	    
		cp.addButton(startOver);  
	    cp.setButtonAlign(HorizontalAlignment.CENTER);  
	    cp.setLayout(new FitLayout());  
	    cp.setSize(Window.getClientWidth(), 500); 

	    
	    Grid<NodeData> grid = new Grid<NodeData>(store, cm);  
	    grid.setSelectionModel(sm);  
	    grid.setAutoExpandColumn("description"); 
	    grid.setAutoExpandMax(2000);
	    grid.setColumnReordering(true);  
	    grid.setBorders(true);  
	    grid.addPlugin(sm);  
	    grid.addPlugin(expander);  
	    grid.getAriaSupport().setLabelledBy(cp.getHeader().getId() + "-label");  
	    
	    cp.add(grid);  

	    sm.setSelection(preSelectionList);
	    
	    RootPanel.get("dataTable").add(cp);		
		
	}
	
	
}